package com.ape.mapsa.common;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.el.MethodExpression;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.MethodExpressionActionListener;

import org.apache.log4j.Logger;
import org.primefaces.component.menuitem.MenuItem;
import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.MenuModel;

import com.ape.mapsa.produccion.constants.TipoMaquina;
import com.ape.mapsa.produccion.model.Maquina;
import com.ape.mapsa.produccion.service.IProduccionService;

@ManagedBean(name = "maqMB")
@ViewScoped
public class MaquinasBean extends BeanCRUD implements Serializable {

	private static final long serialVersionUID = -1865358477053230245L;

	private static final Logger log = Logger.getLogger(MaquinasBean.class);

	@ManagedProperty(value = "#{produccionService}")
	private IProduccionService prodService;

	@ManagedProperty(value = "#{userMB}")
	private UserBean userBean;

	private List<Maquina> maquinas;
	private List<Maquina> maquinasFiltradas;
	private Maquina selectedMaquina = null;
	private String selectedMaquinaCode;

	private TipoMaquina[] maquinaTipos = TipoMaquina.values();
	private TipoMaquina selectedTipoMaquina;

	private boolean rowSelected = false;

	private boolean showAbm = false;

	private Maquina newMaquina;

	@PostConstruct
	public void initialize() {
		log.info("Initializing ITEMS BEAN");
		newMaquina = new Maquina();
		selectedTipoMaquina = TipoMaquina.EXTRUSORA;
		maquinas = new ArrayList<Maquina>();
		maquinasFiltradas = new ArrayList<Maquina>();
		initilizeSubmenu();
	}

	public void updateValue() {  
		log.debug("value updated");
	}
	
	public void searchMaquinasByFilter(ActionEvent event) {
		log.debug("Buscando maquina por tipo: " + selectedTipoMaquina.getNombre());
		maquinas = new ArrayList<Maquina>();
		maquinas = prodService.getMaquinasByType(selectedTipoMaquina.getValor());
	}

	public List<String> buscarMaquinaByCode(String query) {
		List<Maquina> maquinasByCode = prodService.findMaquinaTypeByCode(query);
		List<String> codigos = new ArrayList<String>();
		for (Maquina maquina : maquinasByCode) {
			codigos.add(maquina.getMaqCodigo());
		}
		return codigos;
	}

	public void maquinaCodeSeleccionada(SelectEvent event) {
		maquinas = prodService.getMaquinas();
		for (Maquina maquina : maquinas) {
			log.debug(maquina);
		}
		maquinasFiltradas.addAll(maquinas);

		FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Selected:" + event.getObject().toString(), null);
		FacesContext.getCurrentInstance().addMessage(null, message);
	}

	private void initilizeSubmenu() {
		MenuItem mi = new MenuItem();
		mi.setId("newMaquina");
		mi.setValue("Agregar Maquina");
		mi.setProcess("@this");
		mi.setUpdate(":abmForm:abm_id");
		FacesContext context = FacesContext.getCurrentInstance();
		MethodExpression saveAl = context.getApplication().getExpressionFactory()
				.createMethodExpression(context.getELContext(), "#{maqMB.create}", null, new Class[] { ActionEvent.class });
		mi.addActionListener(new MethodExpressionActionListener(saveAl));
		archivo.getChildren().add(mi);

		mi = new MenuItem();
		mi.setProcess("@this");
		mi.setId("editMaquina");
		mi.setUpdate(":abmForm:abm_id");
		mi.setValue("Editar");
		MethodExpression edit = context.getApplication().getExpressionFactory()
				.createMethodExpression(context.getELContext(), "#{maqMB.edit}", null, new Class[] { ActionEvent.class });
		mi.addActionListener(new MethodExpressionActionListener(edit));
		archivo.getChildren().add(mi);
	}

	public void editarMaquina(ActionEvent actionEvent) {
		log.info("Editando Maquina " + selectedMaquina);
		newMaquina = selectedMaquina;
	}

	public void reset(ActionEvent actionEvent) {
		log.info("Reseting mauina data");
		newMaquina = new Maquina();
		showAbm = false;
		RequestContext.getCurrentInstance().update("abmForm:abm_id");
	}

	public void rowSelected(SelectEvent event) {
		log.debug("rowSelected");
		setRowSelected(selectedMaquina != null);
	}

	private boolean isCodeDuplicated(Maquina maquina) {
		if (maquina.getMaqCodigo() != null) {
			if (prodService.getMaquinaByCode(maquina) != null) {
				return true;
			}
		}
		return false;
	}

	@PreDestroy
	public void predestroy() {
		log.info("MAQUINAS BEAN BEAN IS GOING TO BE DESTROYED");
	}

	public IProduccionService getProdService() {
		return prodService;
	}

	public void setProdService(IProduccionService prodService) {
		this.prodService = prodService;
	}

	@Override
	public void save(ActionEvent event) {
		FacesContext context = FacesContext.getCurrentInstance();
		log.info("Updating: " + newMaquina);

		if (isCodeDuplicated(newMaquina)) {
			RequestContext requestContext = RequestContext.getCurrentInstance();
			requestContext.addCallbackParam("isValid", false);
			FacesMessage codigoDuplicado = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "Codigo de Maquina duplicado.");
			context.addMessage(null, codigoDuplicado);
			return;
		}

		try {
			if (newMaquina.getId() != null) {
				newMaquina.setLastModified(new Date());
				newMaquina.setIsActive(true);
				prodService.updateMaquina(newMaquina);
			} else {
				newMaquina.setCreatedBy(userBean.getEmail());
				newMaquina.setIsActive(true);
				newMaquina.setLastModified(new Date());
				prodService.addMaquina(newMaquina);
				if (newMaquina.getMaqTipo() == selectedTipoMaquina.getValor()) {
					maquinas.add(newMaquina);
				}
			}
			showAbm = false;
			FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, newMaquina.getMaqCodigo(), "Fue guardado satisfactoriamente");
			context.addMessage("abmForm:addMessages", msg);
		} catch (Exception ex) {
			ex.printStackTrace();
			FacesMessage exceptionEnGuardar = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "La Maquina no pudo ser guardada.");
			context.addMessage("abmForm:addMessages", exceptionEnGuardar);
			return;
		}
	}

	@Override
	public void update(ActionEvent event) {
		log.info("Actualizando ITEMS BEAN");
		newMaquina = new Maquina();
		maquinas = new ArrayList<Maquina>();
		maquinas = prodService.getMaquinasByType(selectedTipoMaquina.getValor());

		RequestContext.getCurrentInstance().update("abmForm:abm_id");
		RequestContext.getCurrentInstance().update("abmForm:maquinas:maquinas");
	}

	public void edit(ActionEvent event) {
		log.info("Editando maquina nueva");
		newMaquina = selectedMaquina;
		log.debug("maquina reseted: " + newMaquina);
		showAbm = true;
		RequestContext.getCurrentInstance().update("abmForm:abm_id");
		RequestContext.getCurrentInstance().update("abmForm:maquinas:maquinas");
	}

	@Override
	public void create(ActionEvent event) {
		log.info("Creando maquina nueva");
		newMaquina = new Maquina();
		log.debug("maquina reseted: " + newMaquina);
		showAbm = true;
		RequestContext.getCurrentInstance().update("abmForm:abm_id");
	}

	@Override
	public void delete(ActionEvent event) {
		FacesContext context = FacesContext.getCurrentInstance();
		log.info("Deleting: " + newMaquina);

		if (selectedMaquina == null) {
			RequestContext requestContext = RequestContext.getCurrentInstance();
			requestContext.addCallbackParam("isValid", false);
			FacesMessage codigoDuplicado = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "Debe seleccionar una maquina");
			context.addMessage(null, codigoDuplicado);
			return;
		}
		try {
			newMaquina.setLastModified(new Date());
			newMaquina.setIsActive(false);
			prodService.updateMaquina(newMaquina);
			FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, newMaquina.getMaqCodigo(), "Fue desactivada satisfactoriamente");
			context.addMessage("abmForm:addMessages", msg);
		} catch (Exception ex) {
			ex.printStackTrace();
			FacesMessage exceptionEnGuardar = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "La Maquina no pudo ser desactivada.");
			context.addMessage("abmForm:addMessages", exceptionEnGuardar);
			return;
		}
		RequestContext.getCurrentInstance().update("abmForm:maquinas:maquinas");
	}

	@Override
	public MenuModel getMenuModel() {
		return menuModel;
	}

	public boolean isShowAbm() {
		return showAbm;
	}

	public void setShowAbm(boolean showAbm) {
		this.showAbm = showAbm;
	}

	public UserBean getUserBean() {
		return userBean;
	}

	public void setUserBean(UserBean userBean) {
		this.userBean = userBean;
	}

	public List<Maquina> getMaquinas() {
		return maquinas;
	}

	public void setMaquinas(List<Maquina> maquinas) {
		this.maquinas = maquinas;
	}

	public List<Maquina> getMaquinasFiltradas() {
		return maquinasFiltradas;
	}

	public void setMaquinasFiltradas(List<Maquina> maquinasFiltradas) {
		this.maquinasFiltradas = maquinasFiltradas;
	}

	public Maquina getSelectedMaquina() {
		return selectedMaquina;
	}

	public void setSelectedMaquina(Maquina selectedMaquina) {
		this.selectedMaquina = selectedMaquina;
	}

	public boolean isRowSelected() {
		return rowSelected;
	}

	public void setRowSelected(boolean rowSelected) {
		this.rowSelected = rowSelected;
	}

	public Maquina getNewMaquina() {
		return newMaquina;
	}

	public void setNewMaquina(Maquina newMaquina) {
		this.newMaquina = newMaquina;
	}

	public TipoMaquina[] getMaquinaTipos() {
		return maquinaTipos;
	}

	public void setMaquinaTipos(TipoMaquina[] maquinaTipos) {
		this.maquinaTipos = maquinaTipos;
	}

	public TipoMaquina getSelectedTipoMaquina() {
		return selectedTipoMaquina;
	}

	public void setSelectedTipoMaquina(TipoMaquina selectedTipoMaquina) {
		this.selectedTipoMaquina = selectedTipoMaquina;
	}

	public String getSelectedMaquinaCode() {
		return selectedMaquinaCode;
	}

	public void setSelectedMaquinaCode(String selectedMaquinaCode) {
		this.selectedMaquinaCode = selectedMaquinaCode;
	}

}
